#include "rk3399_gpio_opr.h"
#include <asm/io.h>
#include <linux/string.h>

static volatile unsigned int* CRU_CLKGATE_CON31;
static volatile unsigned int* GRF_GPIO2D_IOMUX;
static volatile unsigned int* GPIO2_SWPORTA_DDR;
static volatile unsigned int* GPIO2_SWPORTA_DR;
static volatile unsigned int* GRF_GPIO2C_IOMUX;

int get_specific_gpio_pin(const char* pin) {
	char group, num;

	if (strlen(pin) != 2)
		return -1;

	group = pin[ 0 ];
	num   = pin[ 1 ];

	if (group > 'D' || group < 'A' || num > '7' || num < '0')
		return -1;

	return (group - 'A') * 8 + (num - '0');
}
// int get_gpio_pin(char group, int num) {
// 	if (group > 'D' || group < 'A')
// 		return -1;

// 	if (num > 7 || num < 0)
// 		return -2;

// 	return (group - 'A') * 8 + num;
// }

/* GPIO2_D1 */
void set_gpio2_status(int pin, int status) {
	if (status > 1 || status < 0 || pin > 31 || pin < 0) {
		printk(KERN_ALERT "illegal pin : %d, status : %d \n", pin, status);
		return;
	}

	if (status)
		*GPIO2_SWPORTA_DR |= (1 << pin);
	else
		*GPIO2_SWPORTA_DR &= ~(1 << pin);

	printk(KERN_INFO "set GPIO2-%d state %d \n", pin, status);
	printk(KERN_INFO "GPIO2_DR : %x \n", *GPIO2_SWPORTA_DR);
}

/* dir 0 input ,1 output */
void set_gpio2_dir(int pin, int dir) {
	if (pin > 31 || pin < 0 || dir > 1 || dir < 0) {
		printk(KERN_ALERT "illegal pin : %d, dir : %d \n", pin, dir);
		return;
	}

	if (dir)
		*GPIO2_SWPORTA_DDR |= (1 << pin);
	else
		*GPIO2_SWPORTA_DDR &= ~(1 << pin);

	printk(KERN_INFO "set GPIO2-%d dir %d \n", pin, dir);
	printk(KERN_INFO "GPIO2_DDR : %x \n", *GPIO2_SWPORTA_DDR);
}

void init_gpio(void) {
	CRU_CLKGATE_CON31 = ioremap(0xFF760000 + 0x037c, 4);
	GRF_GPIO2C_IOMUX  = ioremap(0xFF770000 + 0x0e008, 4);
	GRF_GPIO2D_IOMUX  = ioremap(0xFF770000 + 0x0e00c, 4);
	GPIO2_SWPORTA_DDR = ioremap(0xFF780000 + 0x0004, 4);
	GPIO2_SWPORTA_DR  = ioremap(0xFF780000 + 0x0000, 4);

	*CRU_CLKGATE_CON31 = (1 << (3 + 16)) | (0 << 3);
	/* set gpio D0,D1,C4,C5,C6,C7 function (normal gpio) */
	*GRF_GPIO2D_IOMUX = (3 << (0 * 2 + 16)) | (0 << 0 * 2);
	*GRF_GPIO2D_IOMUX = (3 << (1 * 2 + 16)) | (0 << 1 * 2);
	*GRF_GPIO2C_IOMUX  = (3 << (4*2 + 16)) | (0 << 4*2);
	*GRF_GPIO2C_IOMUX  = (3 << (5*2 + 16)) | (0 << 5*2);
	*GRF_GPIO2C_IOMUX  = (3 << (6*2 + 16)) | (0 << 6*2);
	*GRF_GPIO2C_IOMUX  = (3 << (7*2 + 16)) | (0 << 7*2);
}